package main

import (
	"bytes"
	"encoding/binary"
	"os"
)

func newWavFile(fn string, channels int16, samplesPerSec int32, blockAlign int16) *os.File {
	fp, err := os.Create(fn)
	if err != nil {
		panic(err)
	}
	hdr := createWavHeader(channels, samplesPerSec, blockAlign)
	fp.Write(hdr)
	return fp
}

var hdrSize int32

func endWaveFile(fp *os.File, dataSize int32) {
	var sizeD8 int32 = dataSize + hdrSize - 8
	var buf [4]byte
	binary.LittleEndian.PutUint32(buf[:], uint32(sizeD8))
	fp.Seek(4, 0)
	fp.Write(buf[:])

	binary.LittleEndian.PutUint32(buf[:], uint32(dataSize))
	fp.Seek(40, 0)
	fp.Write(buf[:])
}

/*
{
	char            riff[4];                // = "RIFF"
	int				size_8;                 // = FileSize - 8
	char            wave[4];                // = "WAVE"
	char            fmt[4];                 // = "fmt "
	int				fmt_size;				// = 下一个结构体的大小 : 16

	short int       format_tag;             // = PCM : 1
	short int       channels;               // = 通道数 : 1
	int				samples_per_sec;        // = 采样率 : 16000
	int				avg_bytes_per_sec;      // = 每秒字节数 : 32000
	short int       block_align;            // = 每采样点字节数 : 2
	short int       bits_per_sample;        // = 量化比特数: 16

	char            data[4];                // = "data";
	int				data_size;              // = 纯数据长度 : FileSize - 44
}
*/

func createWavHeader(channels int16, samplesPerSec int32, blockAlign int16) []byte {
	bitsPerSample := blockAlign * 8
	avgBytesPerSec := samplesPerSec * int32(channels) * int32(blockAlign)
	hdr := bytes.NewBufferString("RIFF")
	//int size-8  = FileSize - 8
	hdr.Write([]byte{0, 0, 0, 0})
	//wave = "WAVE"
	//fmt = "fmt "
	hdr.WriteString("WAVEfmt ")
	//int fmt_size = 16
	hdr.Write(bytesInt32(16))
	//short int format_tag = 1
	hdr.Write(bytesInt16(1))
	//short int       channels=1
	hdr.Write(bytesInt16(channels))
	//int				samples_per_sec==16000
	hdr.Write(bytesInt32(samplesPerSec))
	//int				avg_bytes_per_sec=32000
	hdr.Write(bytesInt32(avgBytesPerSec))
	//short int       block_align=2
	hdr.Write(bytesInt16(blockAlign))
	//short int       bits_per_sample=16
	hdr.Write(bytesInt16(bitsPerSample))
	//data = "data"
	hdr.WriteString("data")
	//int				data_size = FileSize - 44
	hdr.Write([]byte{0, 0, 0, 0})
	hdrSize = int32(hdr.Len())
	return hdr.Bytes()
}

func bytesInt32(v int32) []byte {
	var buf [4]byte
	binary.LittleEndian.PutUint32(buf[:], uint32(v))
	return buf[:]
}

func bytesInt16(v int16) []byte {
	var buf [2]byte
	binary.LittleEndian.PutUint16(buf[:], uint16(v))
	return buf[:]
}

func getWavInfo(wavHeader []byte) (samplesPerSec int, channels int, blockAlign int) {
	channelsBytes := wavHeader[22:24]
	samplesPerSecBytes := wavHeader[24:28]
	blockAlignBytes := wavHeader[32:34]
	samplesPerSec = int(binary.LittleEndian.Uint32(samplesPerSecBytes))
	channels = int(binary.LittleEndian.Uint16(channelsBytes))
	blockAlign = int(binary.LittleEndian.Uint16(blockAlignBytes))
	return
}
